﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using DG.Tweening;
using System;
using Bingo;
using Bingo.Config;
using Bingo.Facades;
using Bingo.LocalDB;
using Bingo.LocalDB.Entity;
using QFramework;
using Random = UnityEngine.Random;

public class GameManager: MonoBehaviour
{
    private const string READY_BUBBLE_NUM = "READY_BUBBLE_NUM";

    private const string NEXT_BUBBLE_NUM = "NEXT_BUBBLE_NUM";

    private const string LAST_SCORE = "LAST_SCORE";

    [HideInInspector]
    public bool canFire = true;

    [HideInInspector]
    public bool canClick = true;

    private bool isPressed;

    public Transform readyTrans;

    public Transform nextTrans;

    private Vector2 startPos;

    private Vector2 endPos;

    public Transform firePos;

    [HideInInspector]
    public Bubble readyBubble;

    [HideInInspector]
    public Bubble nextBubble;

    [HideInInspector]
    public int maxNumber = 1;

    public Transform arrow;

    public LineRenderer arrowLine;

    public Vector3 fireDir = Vector3.up;

    public List<Transform> startingBubblePositions;

    public Canvas canvas;

    public static GameManager Instance;

    //public List<Color> numberColors;

    public long score = 0;

    private List<GameObject> arrowDots;

    private Dictionary<long, Dictionary<long, Bubble>> _bubbleStore;

    //public Color GetColor(int number)
    //{
    //    --number;
    //    return this.numberColors[number % this.numberColors.Count];
    //}

    private GameObject cloud;

    private Vector3 cloudPos;

    //public ParticleSystem steam;

    public ParticleSystem boom;

    public Transform boomParent;

    //public GameObject laser;

    public GameObject bubbleBg;

    public int fireStatus;

    public Vector3 readyBubbleScale;

    public Vector3 nextBubbleScale;

    public GameObject HammerParent;

    private Animator HammerAnim;

    private ParticleSystem HammerPs;

    public GameObject bubblePre;

    public Transform trailPsTrans;

    public GameObject trailPs;

    public int fireCount;

    public int Hp;

    private void Awake()
    {
        Instance = this;
        arrowLine = this.arrow.GetComponentInChildren<LineRenderer>();
        _bubbleStore = new Dictionary<long, Dictionary<long, Bubble>>();
        arrowDots = new List<GameObject>();
        cloud = this.transform.Find("Cloud").gameObject;
        cloudPos = this.cloud.transform.position;
        readyBubbleScale = new Vector3(0.5f, 0.5f, 0.5f);
        nextBubbleScale = new Vector3(0.5f, 0.5f, 0.5f);
        HammerAnim = this.HammerParent.transform.Find("Anim_chuizi").GetComponent<Animator>();
        HammerPs = this.HammerParent.transform.Find("EFF_chuizi_yanwu").GetComponent<ParticleSystem>();
        //TODO 数据存储
        /*fireCount = DBHelper.Get<int>(DBKeys.FireCount, 0);
        DBHelper.Save(DBKeys.FireCount, fireCount);
        Hp = DBHelper.Get<int>(DBKeys.HP, 3);
        DBHelper.Save(DBKeys.HP, Hp);*/
    }

    private void Start()
    {
        fireDir = Vector3.up;
        arrow.transform.position = this.firePos.position;
        BornArrow();
        //BornBubblePre();
        canvas.worldCamera = Camera.main;
        //TODO 事件系统
        /*GameEntry.EventSystem.Subscribe(ExchangeEventArgs.Name, OnExchangeHandler);
        GameEntry.EventSystem.Subscribe(BroomEventArgs.Name, OnBroomHandler);
        GameEntry.EventSystem.Subscribe(CloudEventArgs.Name, this.OnCloudHandler);
        GameEntry.EventSystem.Subscribe(ResetEventArgs.Name, OnResetHandler);*/
        this.StartGame();

        //this.bubbleBg.transform.localScale = this.readyBubble.transform.localScale;
        canFire = true;
        this.readyBubble.gameObject.tag = "readybubble";
    }

    public void BornArrow()
    {
        //TODO 资源加载
        /*string bundleName = "gameresources.unity3d";
        GameEntry.Res.LoadBundle(bundleName);
        GameObject arrowPrefab = (GameObject) GameEntry.Res.GetAsset(bundleName, "ArrowDot");
        // GameObject arrowPrefab = 
        Vector2 v = fireDir.normalized;
        for (int i = 0; i < 20; i++)
        {
            GameObject go = UnityEngine.Object.Instantiate(arrowPrefab);
            go.transform.SetParent(this.arrow);
            go.transform.localScale = Vector3.one * 0.1f;
            go.transform.localPosition = i * v * 30;
            this.arrowDots.Add(go);
        }*/
    }

    //public void BornBubblePre()
    //{
    //    string bundleName = "gameresources.unity3d";
    //    GameEntry.Res.LoadBundle(bundleName);
    //    bubblePre = (GameObject)GameEntry.Res.GetAsset(bundleName, "BubblePre");
    //    Instantiate(bubblePre, BubbleSpawner.Instance.bubbleParent);
    //    bubblePre.gameObject.SetActive(false);
    //}

    public void UpdateTransPosition()
    {
        // Debug.Log("----> firdir : " + this.fireDir.normalized);
        Vector2 v = fireDir.normalized;
        Vector2 n = this.fireDir.x > 0? Vector2.left : Vector2.right; //确定法线方向
        Vector2 reflectionV = v - 2 * Vector2.Dot(v, n) * n;
        Vector2 lastV = Vector2.zero;
        float bubbleR = this.readyBubble.BubbleR();
        float maxX = (this.fireDir.x > 0? 1 : -1) * (230 - bubbleR);
        Vector2 refP = maxX / v.x * v;
        // float refX = 
        bool refStatus = false;
        for (int i = 0; i < this.arrowDots.Count; i++)
        {
            GameObject go = this.arrowDots[i];
            Vector2 tmpV = lastV;
            if (!refStatus)
                tmpV = lastV + v * 30;

            if (Mathf.Abs(tmpV.x) > Mathf.Abs(maxX))
            {
                if (!refStatus)
                {
                    refStatus = true;
                    tmpV = refP;
                }
            }
            else if (refStatus)
            {
                tmpV = lastV + reflectionV * 30;
                //Debug.Log("tempv:" + tmpV);
            }

            go.transform.localPosition = tmpV;
            lastV = tmpV;

            // Debug.Log("-----> dot pos : " + go.transform.localPosition);
        }
    }

    /// <summary>
    /// 消除一个最小的球
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void OnBroomHandler(object sender)
    {
        //this.laser.SetActive(false);
        //this.laser.SetActive(true);
        StopCoroutine(DestroyBubble());
        StartCoroutine(DestroyBubble());
    }

    IEnumerator DestroyBubble()
    {
        List<Bubble> bubbles = GetLowestBubbles();
        Bubble a = bubbles[0];
        for (int i = 0; i < bubbles.Count; i++)
        {
            float max = bubbles[0].transform.position.y;
            if (max <= bubbles[i].transform.position.y)
            {
                a = bubbles[i];
            }
        }

        //Bubble bubble = GetLowestBubble();
        if (a != null)
        {
            HammerEff(a.transform);
            yield return new WaitForSeconds(1f);
            a.Destroy();
        }
    }

    public void HammerEff(Transform bubbletrans)
    {
        this.HammerParent.transform.position = bubbletrans.position;
        this.HammerAnim.gameObject.SetActive(true);
        this.HammerAnim.Play("Anim_chuizi", 0, 0);
        this.HammerPs.Play();
    }

    private void OnExchangeHandler(object sender)
    {
        int num = this.nextBubble.number;
        this.nextBubble.SetNumber(this.readyBubble.number);
        this.readyBubble.SetNumber(num);
        NumberManager.Instance.ExchangeNumber();
        ExchangeFeedback(this.readyBubble, this.readyBubble.GetComponent<RectTransform>().localScale);
        //Debug.Log("readybubble.scale:" + this.readyBubble.GetComponent<RectTransform>().localScale);
        ExchangeFeedback(this.nextBubble, this.nextBubble.GetComponent<RectTransform>().localScale);
        //Debug.Log("nextbubble.scale:" + this.nextBubble.GetComponent<RectTransform>().localScale);
    }

    public void ExchangeFeedback(Bubble bubble, Vector3 scale)
    {
        Vector3 targetScale = new Vector3(0.1f, 0.1f, 0.1f);
        Tweener tweener = bubble.GetComponent<RectTransform>().DOScale(targetScale, 0.2f);
        tweener.OnComplete(() => bubble.GetComponent<RectTransform>().DOScale(scale, 0.2f));
    }

    private void OnResetHandler(object sender)
    {
        int a = NumberManager.Instance.GetNumber();
        int b = NumberManager.Instance.GetNumber();
        ExchangeFeedback(this.readyBubble, this.readyBubble.GetComponent<RectTransform>().localScale);
        ExchangeFeedback(this.nextBubble, this.nextBubble.GetComponent<RectTransform>().localScale);
        this.readyBubble.SetNumber(a, false);
        this.nextBubble.SetNumber(b, false);
        NumberManager.Instance.SetNewNumber(a, b);
    }

    private void OnCloudHandler(object sender)
    {
        BubbleForce();
    }

    private void BubbleForce()
    {
        GameObject[] bubbles = GameObject.FindGameObjectsWithTag("bubble");
        for (int i = 0; i < bubbles.Length; i++)
        {
            bubbles[i].GetComponent<Rigidbody2D>().AddForce(new Vector2(0, 50), ForceMode2D.Impulse);
        }


        this.cloud.SetActive(true);
        //this.cloudRigidbody.isKinematic = false;
        StopCoroutine(ResetCloud());
        StartCoroutine(ResetCloud());
        //this.cloudRigidbody.isKinematic = true;
// >>>>>>> 添加虚拟元素
    }

    private IEnumerator ResetCloud()
    {
        yield return new WaitForSeconds(0.2f);
        this.cloud.transform.position = cloudPos;
        this.cloud.transform.rotation = Quaternion.Euler(Vector3.zero);
        this.cloud.SetActive(false);
    }

    private void Update()
    {
/*<<<<<<< HEAD
        this.endPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        //Debug.Log("endpos:" + endPos);
        if (this.readyBubble == null || Input.mousePosition.y <= Screen.height * 0.22f)
            return;

        if (Input.GetKeyDown(KeyCode.Q))
        {
            //this.GameOver();
        }

        //FireMode_Click();

        FireMode_Pull();

    }

    private float pullDistance;
    private float minPullDis;
    private float maxPullDis;
    private float minFireForce = 1000;
    private float maxFireForce = 2400;

    public float currentForce()
    {
        float outputForce = minFireForce + (pullDistance - minPullDis) * ((maxFireForce - minFireForce) / (maxPullDis - minPullDis));
        return outputForce;
    }

    public void FireMode_Pull()
    {
        this.minPullDis = this.readyBubble.GetComponent<RectTransform>().offsetMax.x / 2;
        this.maxPullDis = this.readyBubble.GetComponent<RectTransform>().offsetMax.x * 3 / 2;
        if (Input.GetMouseButtonDown(0))
        {
            this.startPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            Debug.Log("minpulldis:" + minPullDis + " maxpulldis:" + maxPullDis);//32 96
            this.isPressed = true;
            this.arrow.gameObject.SetActive(true);

        }
        else if (this.isPressed && Input.GetMouseButton(0))
        {
            this.arrow.gameObject.SetActive(true);
            Vector3 inputPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            fireDir = inputPos - this.firePos.position;
            UpdateTransPosition();
            SetBubblePre();
            pullDistance = (endPos - startPos).magnitude;
            //Debug.Log("startpos:" + startPos + " endpos:" + endPos + " distance:" + pullDistance);
        }
        else
        {
            if (pullDistance >= minPullDis && pullDistance <= maxPullDis && Input.GetMouseButtonUp(0))
            {
                this.readyBubble.fireForce = currentForce();
                Debug.Log("currentfireforce:" + currentForce());
                this.readyBubble.SetNumber(NumberManager.Instance.GetCurrentNumber(), false);
                this.readyBubble.Fire(fireDir.normalized);
                SaveBubble(this.readyBubble);
                this.StartCoroutine(this.WaitForSpawnNextBubble());
                this.canFire = false;
                this.arrow.gameObject.SetActive(false);
                this.bubblePre.SetActive(false);
            }
            else
            {
                this.canFire = false;
                this.arrow.gameObject.SetActive(false);
                this.bubblePre.SetActive(false);
            }
        }
    }

    public void FireMode_Click()
    {
        if (Input.GetMouseButtonDown(0))
=======*/

        if (this.readyBubble != null && (Input.mousePosition.y > Screen.height * 0.18f))
        {
            if (Input.GetKeyDown(KeyCode.Q))
            {
                this.GameOver();
            }

            //if (this.readyBubble != null)
            //{
            //    this.bubbleBg.transform.localScale = this.readyBubble.transform.localScale;
            //}

            //Debug.Log("canfire:"+canFire);
            if (Input.GetMouseButtonDown(0))
            {
                this.isPressed = true;
                this.startPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
                this.arrow.gameObject.SetActive(true);
                //Debug.Log("-----> startPos : " + this.startPos);
                //SetBubblePre();
            }
            else if (this.isPressed && Input.GetMouseButton(0))
            {
                this.arrow.gameObject.SetActive(true);
                Vector3 inputPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
                // Debug.Log("======> mousePos : " + inputPos + ", firePos : " + this.firePos.position);
                this.fireDir = inputPos - this.firePos.position;
                this.UpdateTransPosition();

                this.SetBubblePre();
            }
            else
            {
                if (this.canFire && this.isPressed && Input.GetMouseButtonUp(0))
                {
                    this.readyBubble.SetNumber(NumberManager.Instance.GetCurrentNumber(), false);
                    this.readyBubble.Fire(this.fireDir.normalized);
                    // Debug.Log("------------------->nextRound : " + this.nextRound);
                    this.SaveBubble(this.readyBubble);
                    this.StartCoroutine(this.WaitForSpawnNextBubble());
                    this.canFire = false;
                    this.arrow.gameObject.SetActive(false);
                    this.bubblePre.SetActive(false);
                }
            }
        }

        this.CheckNextRound();
        //this.nextBubble.GetComponent<CircleCollider2D>().isTrigger = true;

        /*if (!this.nextRound)
        {
            Debug.Log("2 --------------------------------->nextRound " + this.nextRound);
        }*/

    }

    private bool nextRound = true;

    private void CheckNextRound()
    {
        //检测下一个回合状态
        bool running = false;

        foreach (KeyValuePair<long, Dictionary<long, Bubble>> item in _bubbleStore)
// >>>>>>> 添加虚拟元素
        {
            foreach (var bubbleItem in item.Value)
            {
                Bubble bubble = bubbleItem.Value;
                if (bubble.status == BubbleStatus.RUNNING)
                {
                    // Debug.Log("------------->CheckNextRound  bubble.status :" + bubble.status);
                    running = true;
                    break;
                }
            }

            if (running)
            {
                break;
            }
        }
/*<<<<<<< HEAD
        else if (this.isPressed && Input.GetMouseButton(0))
        {
            this.arrow.gameObject.SetActive(true);
            Vector3 inputPos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            fireDir = inputPos - this.firePos.position;
            // this.arrow.up = ((Vector2) (fireDir)); //new Vector2(Screen.width / 2f, Screen.height / 8f)).normalized;
            UpdateTransPosition();
            SetBubblePre();
            //if (this.arrow.eulerAngles.z < 180.0)
            //    this.arrow.eulerAngles = new Vector3(0.0f, 0.0f, Mathf.Clamp(this.arrow.eulerAngles.z, -60f, 60f));
            //else
            //    this.arrow.eulerAngles = new Vector3(0.0f, 0.0f, Mathf.Clamp(this.arrow.eulerAngles.z, 300f, 360f));
=======*/

        if (!running)
        {
            // Debug.Log("------------------- running " + running + ", nextRound : " + this.nextRound);
// >>>>>>> 添加虚拟元素
        }

        if (!running && !this.nextRound)
        {
            this.nextRound = true;
            this.NextRound();
        }
    }

    public List<BubbleData> GetStorageBubbles()
    {
        List<BaseObject> objs = LocalDB.GetByType(typeof(BubbleData).Name);
        List<BubbleData> datas = new List<BubbleData>();
        foreach (BaseObject o in objs)
        {
            string str = (string) o["Value"];
            // Debug.Log("---------------------------> str : " + str);
            BubbleData data = str.FromJson<BubbleData>();// BsonSerializer.Deserialize<BubbleData>(str);
            datas.Add(data);
        }

        return datas;
        return null;
    }

    public void StartGame()
    {
        score = 0;
        BubbleSpawner.Instance.GameStart();
        List<BubbleData> localBubbles = GetStorageBubbles();
        if (localBubbles.Count > 0)
        {
            for (int i = 0; i < localBubbles.Count; ++i)
            {
                BubbleData data = localBubbles[i];
                Bubble bubble = BubbleSpawner.Instance.GetBubble(data.Id);
                bubble.State = BubbleState.Live;
                bubble.setOnStart = true;
                bubble.SetNumber(data.Number, false);
                bubble.transform.position = new Vector3(data.X, data.Y);
                SaveBubble(bubble);
            }

           //TODO 数据存储
            int readyNum = LocalDB.Get<int>(READY_BUBBLE_NUM);
            int nextNum = LocalDB.Get<int>(NEXT_BUBBLE_NUM);
            this.score = LocalDB.Get<long>(LAST_SCORE);
            NumberManager.Instance.StartFromLoad(readyNum, nextNum);
            TriggerScore(0);
            this.SpawnNextBubble(true);
        }
        else
        {
            for (int i = 0; i < this.startingBubblePositions.Count; ++i)
            {
                Bubble bubble = BubbleSpawner.Instance.GetBubble();
                bubble.State = BubbleState.Live;
                bubble.transform.position = this.startingBubblePositions[i].position;
                bubble.setOnStart = true;
                if (i < 3)
                    bubble.SetNumber(1, false);
                else if (i < 5)
                    bubble.SetNumber(3, false);
                else
                    bubble.SetNumber(5, false);
                // Debug.Log("------------> i : " + i);
                SaveBubble(bubble);
            }
            //BornShadow.instance.SpawnShadowBubble();

            this.maxNumber = 1;
            this.SpawnNextBubble(false);
        }
    }

    private void NextRound()
    {
        //下一回合状态
        Debug.Log("---------------> 下一回合");
        StartCoroutine(this.DoNextRound());
    }

    private IEnumerator DoNextRound()
    {
        yield return null;
        this.NextRoundVirtualBubbles();
    }

    public void RestartGame()
    {
        foreach (Transform trans in BubbleSpawner.Instance.bubbleParent)
        {
            if (trans.gameObject.tag == "bubble" || trans.gameObject.tag == "readybubble")
            {
                Destroy(trans.gameObject);
            }
        }

        _bubbleStore.Clear();
        LocalDB.Delete(NEXT_BUBBLE_NUM);
        LocalDB.Delete(READY_BUBBLE_NUM);
        LocalDB.Delete(LAST_SCORE);
        LocalDB.DeleteAll<BubbleData>();
        NumberManager.Instance.reset();
        canFire = true;
        this.StartGame();
        this.SpawnNextBubble(false);
    }

    public void IncreaseScore(int mScore)
    {
        this.score += mScore;
        TriggerScore(mScore);
    }

    private void TriggerScore(int mScore)
    {
        /*IncreaseEventArgs args = new IncreaseEventArgs();
        args.TotalScore = this.score;
        args.IncreaseScore = mScore;
        GameEntry.EventSystem.Fire(this, args);*/
    }

    private void SpawnNextBubble(bool fromLoad = false)
    {
        if (fromLoad)
        {
            // NumberManager.Instance.GetCurrentNumber(GameSaver.saver.LastNumber);
        }
        else
        {
            NumberManager.Instance.GetANewNumber();
        }

        // Debug.Log("-----> readyBubble");
        if (this.nextBubble == null)
        {
            this.readyBubble = BubbleSpawner.Instance.GetBubble();
            this.readyBubble.State = BubbleState.WaitingToFire;
            this.readyBubble.gameObject.transform.localScale = readyBubbleScale;
            this.readyBubble.SetNumber(NumberManager.Instance.GetCurrentNumber(), false);
        }
        else
        {
            this.readyBubble = this.nextBubble;
            this.readyBubble.gameObject.tag = "readybubble";
            //this.bubbleBg.transform.localScale = this.readyBubble.transform.localScale;
        }

        this.readyBubble.transform.localScale = Vector3.one * 0.5f;
        this.readyBubble.transform.position = this.readyTrans.position;

        this.nextBubble = BubbleSpawner.Instance.GetBubble();
        this.nextBubble.State = BubbleState.WaitingToFire;
        this.nextBubble.gameObject.transform.localScale = nextBubbleScale;
        this.nextBubble.transform.localScale = Vector3.one * 0.5f;
        this.nextBubble.transform.position = this.nextTrans.position;
        this.nextBubble.SetNumber(NumberManager.Instance.GetNextNumber(), false);
    }

    public void discardCurrentOne()
    {
        NumberManager.Instance.discardClicked();
        if (this.readyBubble != null)
            Destroy(this.readyBubble.gameObject);
        this.SpawnNextBubble(false);
        this.canFire = true;
    }

    private IEnumerator WaitForSpawnNextBubble()
    {
        yield return new WaitForSeconds(0.5f);
        this.SpawnNextBubble(false);
        this.nextRound = false;

        this.canFire = true;
    }

    /// <summary>
    /// 保存生成的bubble
    /// </summary>
    /// <param name="bubble"></param>
    public void SaveBubble(Bubble bubble)
    {
        int number = bubble.number;
        long id = bubble.id;
        Dictionary<long, Bubble> bubbleDic;
        if (this._bubbleStore.ContainsKey(number))
        {
            bubbleDic = this._bubbleStore[number];
        }
        else
        {
            bubbleDic = new Dictionary<long, Bubble>();
        }

        bubbleDic[id] = bubble;

        this._bubbleStore[number] = bubbleDic;
    }

    /// <summary>
    /// bubble消除，移除bubble
    /// </summary>
    /// <param name="number"></param>
    /// <param name="id"></param>
    /// <returns></returns>
    public bool RemoveBubble(int number, long id)
    {
        if (this._bubbleStore.ContainsKey(number))
        {
            var bubbleDic = this._bubbleStore[number];
            if (bubbleDic.ContainsKey(id))
            {
                bubbleDic.Remove(id);
                if (bubbleDic.Count == 0)
                {
                    this._bubbleStore.Remove(number);
                }

                return true;
            }
        }

        return false;
    }

    public Bubble GetLowestBubble()
    {
        long number = 0;
        foreach (var item in this._bubbleStore)
        {
            if (number > item.Key || number == 0)
            {
                number = item.Key;
            }
        }

        if (number > 0)
        {
            Dictionary<long, Bubble> bubbleDic = this._bubbleStore[number];
            if (bubbleDic.Count > 0)
            {
                foreach (var item in bubbleDic)
                {
                    return item.Value;
                }
            }
        }

        return null;
    }

    public List<Bubble> GetLowestBubbles()
    {
        List<Bubble> bubbles = new List<Bubble>();
        long number = 0;
        foreach (var item in this._bubbleStore)
        {
            if (number > item.Key || number == 0)
            {
                number = item.Key;
            }
        }

        if (number > 0)
        {
            Dictionary<long, Bubble> bubbleDic = this._bubbleStore[number];
            if (bubbleDic.Count > 0)
            {
                foreach (var item in bubbleDic)
                {
                    bubbles.Add(item.Value);
                }

                return bubbles;
            }
        }

        return null;
    }

    private void OnApplicationPause(bool pauseStatus)
    {
        Debug.Log("---------> OnApplicationPause pauseStatus : " + pauseStatus);
        if (pauseStatus)
        {
            //暂停状态
        }
    }

    private void OnApplicationFocus(bool hasFocus)
    {
        //Debug.Log("---------> OnApplicationFocus hasFocus : " + hasFocus);
        if (!hasFocus)
        {
            SaveBubblesToDB();
        }
    }

    public void BubbleStorage()
    {
    }

    public void SaveBubblesToDB()
    {
        //TODO 数据存储
        List<BubbleData> bubbleList = new List<BubbleData>();
        foreach (var dic in this._bubbleStore)
        {
            foreach (var obj in dic.Value)
            {
                Vector3 v = obj.Value.transform.position;
                bubbleList.Add(new BubbleData() { Id = obj.Value.id, X = v.x, Y = v.y, Number = obj.Value.number });
            }
        }

        Debug.Log("--------------> bubble to save count : " + bubbleList.Count);

        LocalDB.DeleteAll<BubbleData>();
        LocalDB.Insert<BubbleData>(bubbleList);
//        GameEntry.DB.Save(bubbleList);
        LocalDB.Save(READY_BUBBLE_NUM, this.readyBubble.number);
        LocalDB.Save(NEXT_BUBBLE_NUM, this.nextBubble.number);
        LocalDB.Save(LAST_SCORE, this.score);
        this.UpdateBestScore((int) this.score);
    }

    public void GameOver()
    {
//        Destroy(this.nextBubble.gameObject);
        /*GameSaver.saver.Gameover();
        CanvasControl.controller.GameOver();
        this.isPressed = false;*/
    }

    public void UpdateBestScore(int newscore)
    {
        int oldScore = LocalDB.Get<int>(DBKeys.BestScore);
        if (newscore > oldScore)
        {
            oldScore = newscore;
            LocalDB.Save(DBKeys.BestScore, newscore);
        }
    }

    public IEnumerator ChangeFireStatus()
    {
        yield return new WaitForSeconds(0.5f);
        canFire = true;
    }

    public void StartCoroutineChangeFireStatus()
    {
        StartCoroutine(ChangeFireStatus());
    }

    public IEnumerator ButtonInterval(Button button)
    {
        button.interactable = false;
        //canClick = false;
        yield return new WaitForSeconds(0.5f);
        //canClick = true;
        button.interactable = true;
    }

    public void StartCoroutineChangeClickInterval(Button button)
    {
        StartCoroutine(ButtonInterval(button));
    }

    public void SetBubblePre()
    {
        if (arrowDots.Count != 0)
        {
            for (int i = 0; i < arrowDots.Count; i++)
            {
                if (Mathf.Abs(arrowDots[i].transform.localPosition.x) == 180)
                {
                    this.bubblePre.transform.position = arrowDots[i].transform.position;
                    if (bubblePre.transform.localPosition.y < -320f)
                    {
                        this.bubblePre.SetActive(true);
                    }
                    else
                    {
                        this.bubblePre.SetActive(false);
                    }

                    return;
                }
            }
        }
    }

    public void SetTrailPs()
    {
        Instantiate(this.trailPs, this.readyBubble.transform.position, Quaternion.identity, this.trailPsTrans);
    }

    public void GameOverWithNoHp()
    {
    }

    private Bubble _virtualBubble1;
    private Bubble _virtualBubble2;

    private int virtualStatus = 0;

    private void NextRoundVirtualBubbles()
    {
        if (virtualStatus == 0)
        {
            this.virtualStatus = 1;
            this._virtualBubble1 = this.BornVirtualBubbles();
            this._virtualBubble2 = this.BornVirtualBubbles();
        }
        else if (this.virtualStatus == 1)
        {
            this.virtualStatus = 0;
            // if (this._virtualBubble1 != null)
            if (CheckPosition(this._virtualBubble1))
                this._virtualBubble1.SetBubbleLive();
            else
                this._virtualBubble1.Destroy();


            if (CheckPosition(this._virtualBubble2))
                    this._virtualBubble2.SetBubbleLive();
                else
                    this._virtualBubble2.Destroy();
        }
    }

    private bool CheckPosition(Bubble vBubble)
    {
        bool state = true;

        foreach (KeyValuePair<long, Dictionary<long, Bubble>> item in _bubbleStore)
        {
            foreach (var bubbleItem in item.Value)
            {
                Bubble bubble = bubbleItem.Value;
                bool cover = bubble.OverLap(vBubble);
                if (cover)
                    return false;
            }
        }

        return true;
    }

    public Bubble BornVirtualBubbles()
    {
        Bubble bubble = BubbleSpawner.Instance.GetBubble();
        bubble.gameObject.name = "virtual";
        bubble.SetNumber(NumberManager.Instance.GetANewNumber());
        bubble.SetBubbleVirtual();
        // do
        {
            bubble.transform.localPosition = this.GetVirtualPos();
        }
        // while (!CheckPosition(bubble));

        return bubble;
    }

    private Vector2 GetVirtualPos()
    {
        float x = Random.Range(0, 300) * Random.Range(0, 2) == 1? -1 : 1;
        float y = Random.Range(140, 450) * -1;

        return new Vector2(x, y);
// >>>>>>> 添加虚拟元素
    }
}